# -*- coding: utf8 -*-
"""
    We handle all exceptions here and render it.
"""

import sys, pprint
import turbogears, cherrypy

from mnemoply.model import __connection__
from mnemoply.utils import ExceptionsBunch, report_error, escape

@turbogears.expose(template="genshi:mnemoply.templates.lib.show_errors")
def show_errors_handler(object, tg_exceptions=None, tg_errors=None, **kw):
    assert isinstance(tg_exceptions, ExceptionsBunch)

    pairs = tg_exceptions.pairs

    if isinstance(pairs, dict):
        pairs = pairs.items()
        pairs.sort(key=lambda x: x[0])

    __connection__.getConnection().rollback()

    return dict(pairs=tg_exceptions.pairs, title=tg_exceptions.title)

def handle_std_exceptions():
    return turbogears.exception_handler(show_errors_handler,
            "isinstance(tg_exceptions, ExceptionsBunch)")

def get_user_safe():
    try:
        return turbogears.identity.current.user.user_name
    except:
        return ""

def format_traceback(tb):
    result = ""

    while 1:
        if not tb.tb_next:
            break
        tb = tb.tb_next

    stack = []
    f = tb.tb_frame
    while f:
        stack.append(f)
        f = f.f_back

    stack.reverse()
    for frame in stack:
        result += "*** Frame %s in %s at line %s\n" % (frame.f_code.co_name,
                                             frame.f_code.co_filename,
                                             frame.f_lineno)
        for key, value in frame.f_locals.items():
            result += "\t%20s = " % key
            #We have to be careful not to cause a new error in our error
            #printer! Calling str() on an unknown object could cause an
            #error we don't want.
            try:
                result += repr(value).decode("unicode_escape")
            except Exception, ex:
                result += "ERROR WHILE PRINTING VALUE (%s)" % str(ex)
            result += "\n"

    return result

def get_500_text(err_string, assigned_id, traceback_text):
    # Internal Server Error
    HTML_500 = """
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
      "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head>
        <title>Internal Server Error (500)</title>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
        <script type="text/javascript" src="/static/javascript/utils.js"></script>
        <link rel="stylesheet" type="text/css" href="/static/css/error.css"/>
    </head>
    <body>
    <div id="error_wrapper">
    <h1>""" + _("A software problem occurred while processing your request") + """</h1>
    <h3>"""  \
        + _("Short description:") + """
    </h3>
    <p class="error"> %s </p>""" % err_string + \
    "<p>" + _("Error number: ") + "%d</p>" % assigned_id + \
    """<p><a href="javascript:history.back()">""" + _("Back") + """</a>
        <br/>
    </p>
    <a href="javascript:None()" onclick="toggleDisplay('traceback')">""" + _("Description:") + """</a>
    </div>
    <div id="traceback" style="display:none">
      <pre>
        %s
      </pre>
    </div>
    </body>
    </html>""" % traceback_text

    return HTML_500

def error_handler(root):
    try:
        raise
    except Exception, e:
        err = sys.exc_info()
        err_string = str(err[1])
        err_type   = str(err[0])
        traceback_text = str(format_traceback(err[2]))

        # print err_type, err_string
        is_duplicate = err_string.find('Duplicate entry') != -1
        is_production = not turbogears.config.get("under_testing", False)

        # individual page for Duplicate Error
        if is_duplicate and is_production:
            cherrypy.response.body = root.error_DuplicateEntry(e)
            return

        # Build report
        mystr = lambda x: repr(x).decode("unicode_escape")
        req = cherrypy.request
        pp = pprint.PrettyPrinter(depth=6)

        report = ""
        report += "Exception: %s %s\n" % (mystr(err_type), mystr(err_string))
        report += "Request line: %s\n" % req.requestLine
        report += "Params: %s\n" % mystr(req.params)
        report += "Headers: %s\n" % mystr(pp.pformat(req.headers))
        report += "User: %s\n" % get_user_safe()
        report += "Traceback:\n" + traceback_text

        # Send report
        try:
            assigned_id = report_error("500", report)
        except:
            assigned_id = 0

        # Show error to a user
        cherrypy.response.headerMap['Status'] = '500 Internal Server Error'
        cherrypy.response.headerMap['Content-Type'] = 'text/html'
        cherrypy.response.body = get_500_text(err_string=escape(err_string),
            assigned_id=assigned_id,
            traceback_text=escape(traceback_text))


